#!/usr/bin/env python
# encoding: utf-8


"""
@file: jiouxing.py
@time: 2017/3/9 下午4:39
"""
# 三角函数的奇偶性
from mathsolver.functions.base import *
from sympy import sin, cos, tan, pi
from mathsolver.functions.sanjiao import sanjiao_utils as su
from mathsolver.functions.budengshi import common_opers as co
from mathsolver.functions.sanjiao.sanjiao_constants import SanJiaoJiOuXingKey, SanJiaoHanShuJiOuXingType


# 含绝对值的 形式1
# 形如 y = A|sin(w*x + h)| + b
class SanJiaoHanShuJiOuXing001(BaseFunction):
    def solver(self, *args):
        self.label.add('三角函数奇偶性')
        if isinstance(args[0], BaseEq) or isinstance(args[0], BaseIneq):
            _, trig_f = args[0].sympify()
        elif isinstance(args[0], BasePoly):
            trig_f = args[0].sympify()
        elif isinstance(args[0], str):
            trig_f = sympify(args[0])
        else:
            raise Exception("to do")
        x_symbol = sympify('x')
        if str(trig_f).find('Abs') < 0:
            raise Exception('Type Match Error')
        abs_mon = sympify(co.find_reg_expr(r'Abs\(.*?\)', str(trig_f))[0])
        _A = trig_f.coeff(abs_mon)
        ab_arg_trig = abs_mon.args[0]
        if type(ab_arg_trig) not in [sin, cos, tan]:
            raise Exception('Type Match Error')
        t_coef, t_type, t_arg, _2 = su.simp_trig_info(trig_f)
        if t_coef != 1:
            raise Exception('Type Match Error')
        t_arg = sympify(t_arg)
        _w = t_arg.coeff(x_symbol)
        _h = t_arg.subs(x_symbol, 0)
        func_type = SanJiaoHanShuJiOuXingType.NOT_ODD_AND_EVEN_FUNC
        if t_type == sin:
            if (2 * _h) / pi in S.Integers:
                func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        elif t_type == cos:
            if (2 * _h) / pi in S.Integers:
                func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        elif t_type == tan:
            if (2 * _h) / pi in S.Integers:
                func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        self.output.append(BaseSymbolValue({SanJiaoJiOuXingKey: func_type}))
        return self


# 含绝对值的  形式2
# 形如 y = a|A*sin(w*x+h)+b|的形式
class SanJiaoHanShuJiOuXing002(BaseFunction):
    def solver(self, *args):
        self.label.add('三角函数奇偶性')
        if isinstance(args[0], BaseEq) or isinstance(args[0], BaseIneq):
            _, trig_f = args[0].sympify()
        elif isinstance(args[0], BasePoly):
            trig_f = args[0].sympify()
        elif isinstance(args[0], str):
            trig_f = sympify(args[0])
        else:
            raise Exception("to do")
        x_symbol = sympify('x')
        if str(trig_f).find('Abs') < 0:
            raise Exception('Type Match Error')
        abs_mon = sympify(co.find_reg_expr(r'Abs\(.*?\)', str(trig_f))[0])
        _a = trig_f.coeff(abs_mon)
        _A, t_type, t_arg, _b = su.simp_trig_info(trig_f)
        if not (_a != 0 and _A != 0 and _b != 0):
            raise Exception('Type Match Error')
        t_arg = sympify(t_arg)
        _h = t_arg.subs(x_symbol, 0)
        func_type = SanJiaoHanShuJiOuXingType.NOT_ODD_AND_EVEN_FUNC
        if t_type == sin:
            if abs(_b) >= abs(_A):
                if _h / pi in S.Integers and _b == 0:
                    func_type = SanJiaoHanShuJiOuXingType.ODD_FUNC
                elif (_h - pi / 2) / pi in S.Integers:
                    func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
            if abs(_b) < abs(_A):
                if (_h - pi / 2) / pi in S.Integers:
                    func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        elif t_type == cos:
            if abs(_b) >= abs(_A):
                if (_h - pi / 2) / pi in S.Integers and _b == 0:
                    func_type = SanJiaoHanShuJiOuXingType.ODD_FUNC
                elif _h / pi in S.Integers:
                    func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
            if abs(_b) < abs(_A):
                if _h / pi in S.Integers:
                    func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        self.output.append(BaseSymbolValue({SanJiaoJiOuXingKey: func_type}))
        return self


# y = A*sin(w*x + h) + b
class SanJiaoHanShuJiOuXing003(BaseFunction):
    def solver(self, *args):
        self.label.add('三角函数奇偶性')
        if isinstance(args[0], BaseEq) or isinstance(args[0], BaseIneq):
            _, trig_f = args[0].sympify()
        elif isinstance(args[0], BasePoly):
            trig_f = args[0].sympify()
        elif isinstance(args[0], str):
            trig_f = sympify(args[0])
        else:
            raise Exception("to do")
        x_symbol = sympify('x')
        _A, t_type, t_arg, _b = su.simp_trig_info(trig_f)
        _w = trig_f.coeff(x_symbol)
        _h = trig_f.subs(x_symbol, 0)
        func_type = SanJiaoHanShuJiOuXingType.NOT_ODD_AND_EVEN_FUNC
        if t_type == sin:
            if _h / pi in S.Integers and _b == 0:  # _h = k*pi 奇函数
                func_type = SanJiaoHanShuJiOuXingType.ODD_FUNC
            elif (_h - pi / 2) / pi in S.Integers:  # _h = k*pi + pi/2 偶函数
                func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        elif t_type == cos:
            if (_h - pi / 2) / pi in S.Integers and _b == 0:
                func_type = SanJiaoHanShuJiOuXingType.ODD_FUNC
            elif _h / pi in S.Integers:
                func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        elif t_type == tan:
            if (2 * _h) / pi in S.Integers and _b == 0:
                func_type = SanJiaoHanShuJiOuXingType.ODD_FUNC
        self.output.append(BaseSymbolValue({SanJiaoJiOuXingKey: func_type}))
        return self


class SanJiaoHanShuJiOuXingPanDuan(BaseFunction):
    CLS = [SanJiaoHanShuJiOuXing001, SanJiaoHanShuJiOuXing002, SanJiaoHanShuJiOuXing003]

    def solver(self, *args):
        solve_f = None
        for cl in SanJiaoHanShuJiOuXingPanDuan.CLS:
            try:
                solve_f = cl()
                solve_f.known = self.known
                solve_f = solve_f.solver(*args)
            except Exception:
                solve_f = None
        if not solve_f:
            raise Exception('try fail')
        return solve_f


# -----------------------------------------------------------------------------------------------------------------------

# 含绝对值的 形式1
# 形如 y = A|sin(w*x + h)| + b
class SanJiaoHanShuJiOuXingTiaoJian001(BaseFunction):
    def solver(self, *args):
        self.label.add('三角函数奇偶性')
        _k = sympify('k')
        if isinstance(args[0], BaseEq) or isinstance(args[0], BaseIneq):
            _, trig_f = args[0].sympify()
        elif isinstance(args[0], BasePoly):
            trig_f = args[0].sympify()
        elif isinstance(args[0], str):
            trig_f = sympify(args[0])
        else:
            raise Exception("to do")
        x_symbol = sympify('x')
        if str(trig_f).find('Abs') < 0:
            raise Exception('Type Match Error')
        text = args[1]
        func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC if text.find('偶函数') >= 0 else SanJiaoHanShuJiOuXingType.EVEN_FUNC
        eqs = []
        abs_mon = sympify(co.find_reg_expr(r'Abs\(.*?\)', str(trig_f))[0])
        _A = trig_f.coeff(abs_mon)
        ab_arg_trig = abs_mon.args[0]
        if type(ab_arg_trig) not in [sin, cos, tan]:
            raise Exception('Type Match Error')
        t_coef, t_type, t_arg, _2 = su.simp_trig_info(trig_f)
        if t_coef != 1:
            raise Exception('Type Match Error')
        t_arg = sympify(t_arg)
        _w = t_arg.coeff(x_symbol)
        _h = t_arg.subs(x_symbol, 0)
        if t_type == sin:
            if func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:  # _h = k*pi/2
                eq = [_k * pi / 2, _h]
                eqs.append(eq)
        elif t_type == cos:
            if func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                eq = [_k * pi / 2, _h]
                eqs.append(eq)
        elif t_type == tan:
            if func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                eq = [_k * pi / 2, _h]
                eqs.append(eq)
        self.output.append(BaseEqs(eqs))
        return self


# 含绝对值的  形式2
# 形如 y = a|A*sin(w*x+h)+b|的形式
class SanJiaoHanShuJiOuXingTiaoJian002(BaseFunction):
    def solver(self, *args):
        self.label.add('三角函数奇偶性')
        _k = sympify('k')
        if isinstance(args[0], BaseEq) or isinstance(args[0], BaseIneq):
            _, trig_f = args[0].sympify()
        elif isinstance(args[0], BasePoly):
            trig_f = args[0].sympify()
        elif isinstance(args[0], str):
            trig_f = sympify(args[0])
        else:
            raise Exception("to do")
        x_symbol = sympify('x')
        if str(trig_f).find('Abs') < 0:
            raise Exception('Type Match Error')
        text = args[1]
        func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC if text.find(
            '偶函数') >= 0 else SanJiaoHanShuJiOuXingType.EVEN_FUNC
        eqs = []
        abs_mon = sympify(co.find_reg_expr(r'Abs\(.*?\)', str(trig_f))[0])
        _a = trig_f.coeff(abs_mon)
        _A, t_type, t_arg, _b = su.simp_trig_info(trig_f)
        if not (_a != 0 and _A != 0 and _b != 0):
            raise Exception('Type Match Error')
        t_arg = sympify(t_arg)
        _h = t_arg.subs(x_symbol, 0)
        if t_type == sin:
            if abs(_b) >= abs(_A):
                if func_type == SanJiaoHanShuJiOuXingType.ODD_FUNC:
                    eq1 = [_k * pi, _h]
                    eq2 = [_b, 0]
                    eqs.append(eq1)
                    eqs.append(eq2)
                # if _h / pi in S.Integers and _b == 0:
                #     func_type = SanJiaoHanShuJiOuXingType.ODD_FUNC
                elif func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                    eq1 = [_k * pi + pi / 2, _h]
                    eqs.append(eq1)
                    # elif (_h - pi / 2) / pi in S.Integers:
                    #     func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
            if abs(_b) < abs(_A):
                if func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                    eq1 = [_k * pi + pi / 2, _h]
                    eqs.append(eq1)
                    # if (_h - pi / 2) / pi in S.Integers:
                    #     func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
        elif t_type == cos:
            if abs(_b) >= abs(_A):
                if func_type == SanJiaoHanShuJiOuXingType.ODD_FUNC:
                    eq1 = [_k * pi + pi / 2, _h]
                    eq2 = [_b, 0]
                    eqs.append(eq1)
                    eqs.append(eq2)
                    # if (_h - pi / 2) / pi in S.Integers and _b == 0:
                    # func_type = SanJiaoHanShuJiOuXingType.ODD_FUNC
                elif func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                    eq1 = [_k * pi, _h]
                    eqs.append(eq1)
                    # elif _h / pi in S.Integers:
                    #     func_type = SanJiaoHanShuJiOuXingType.EVEN_FUNC
            if abs(_b) < abs(_A):
                if func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                    eq1 = [_k * pi, _h]
                    eqs.append(eq1)
        self.output.append(BaseEqs(eqs))
        return self


# y = A*sin(w*x + h) + b
class SanJiaoHanShuJiOuXingTiaoJian003(BaseFunction):
    def solver(self, *args):
        self.label.add('三角函数奇偶性')
        _k = sympify('k')
        if isinstance(args[0], BaseEq) or isinstance(args[0], BaseIneq):
            _, trig_f = args[0].sympify()
        elif isinstance(args[0], BasePoly):
            trig_f = args[0].sympify()
        elif isinstance(args[0], str):
            trig_f = sympify(args[0])
        else:
            raise Exception("to do")
        x_symbol = sympify('x')
        eqs = []
        _A, t_type, t_arg, _b = su.simp_trig_info(trig_f)
        _w = trig_f.coeff(x_symbol)
        _h = trig_f.subs(x_symbol, 0)
        func_type = SanJiaoHanShuJiOuXingType.NOT_ODD_AND_EVEN_FUNC
        if t_type == sin:
            if func_type == SanJiaoHanShuJiOuXingType.ODD_FUNC:
                eq1 = [_k * pi, _h]
                eq2 = [_b, 0]
                eqs.append(eq1)
                eqs.append(eq2)
            elif func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                eq1 = [_k * pi + pi / 2, _h]
                eqs.append(eq1)
        elif t_type == cos:
            if func_type == SanJiaoHanShuJiOuXingType.ODD_FUNC:
                eq1 = [_k * pi + pi / 2, _h]
                eqs.append(eq1)
            elif func_type == SanJiaoHanShuJiOuXingType.EVEN_FUNC:
                eq1 = [_k * pi, _h]
                eqs.append(eq1)
        elif t_type == tan:
            if func_type == SanJiaoHanShuJiOuXingType.ODD_FUNC:
                eq1 = [_k * pi, 2 * _h]
                eq2 = [_b, 0]
                eqs.append(eq1)
                eqs.append(eq2)
        self.output.append(BaseEqs(eqs))
        return self


# 根据三角函数的奇偶性得出等式条件
class SanJiaoHanShuJiOuXingTiaoJian(BaseFunction):
    CLS = [SanJiaoHanShuJiOuXingTiaoJian001, ]

    def solver(self, *args):
        solve_f = None
        for cl in SanJiaoHanShuJiOuXingTiaoJian.CLS:
            try:
                solve_f = cl()
                solve_f.known = self.known
                solve_f = solve_f.solver(*args)
                solve_f.label.add('三角函数奇偶性')
            except Exception:
                solve_f = None
        if not solve_f:
            raise Exception('try fail')
        return solve_f
